package edu.hawaii.halealohacli.command;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.wattdepot.client.WattDepotClient;

/**
 * This class can be used by the processor class to obtain a list of instances of all the Command
 * classes.
 * 
 * @author Group BackR
 * 
 */
public class CommandManager {

  private static final String RAW = "rawtypes";
  private String[] commands = { "CurrentPower", "DailyEnergy", "EnergySince", "RankTowers", "Help",
      "MonitorPower", "SetBaseline", "MonitorGoal" };

  /**
   * Runs a command class with given method name and user input, then returns back processed data.
   * 
   * @param commandClass The command class to run.
   * @param methodName The method to run.
   * @param runParams The parameters of the method.
   * @param input The user input.
   * @param client The WattDepotClient server.
   * @return The data retrieved from the command class.
   */
  @SuppressWarnings({ RAW, "unchecked" })
  public String run(Class commandClass, String methodName, Class[] runParams, String[] input,
      WattDepotClient client) {
    String output = "";
    // Access the run method from the selected command class.
    try {
      Method runMethod = commandClass.getMethod(methodName, runParams);
      // Create an instance of this class.
      Object thisClassObject = commandClass.newInstance();
      // Run and retrieve data from the run() method.
      if ("run".equals(methodName)) {
        output = (String) runMethod.invoke(thisClassObject, input, client);
      }

      else {
        if ("getNumParams".equals(methodName)) {
          output = Integer.toString((Integer) runMethod.invoke(thisClassObject));
        }
        else {
          output = (String) runMethod.invoke(thisClassObject);
        }
      }
    }
    catch (NoSuchMethodException e) {
      output = "Could not run class method. Please try again.";
    }
    catch (InstantiationException e) {
      output = "Unable to process command. Please try again.";
    }
    catch (Exception e) {
      output = "Unexpected error has occured. Please try again.";
    }
    return output;
  }

  /**
   * Gets all the classes from the package and returns it as a list.
   * 
   * @return The list of classes
   * @throws ClassNotFoundException Could not find the class.
   * @throws IOException File error.
   */
  @SuppressWarnings({ RAW })
  public Class[] getClasses() throws ClassNotFoundException, IOException {
    Class<CommandManager> thisClass = CommandManager.class;
    String packageName = thisClass.getPackage().getName();
    ArrayList<Class> classes = new ArrayList<Class>();
    for (String command : commands) {
      Class c = Class.forName(packageName + "." + command);
      classes.add(c);
    }
    return classes.toArray(new Class[classes.size()]);
  }
}
